package dbservice

import (
	"fmt"
	"net/url"
	"src/zeus/logger"
)

//type LoginUtil = loginPidUtil
//
//
// 账号Id=uid 为key的缓存
//type LoginUtil struct {
//	uid uint64
//}
//
//func GetLoginUtil(uid uint64) *LoginUtil {
//	return &LoginUtil{uid: uid}
//}
//

// 账号Id=uid 为key的缓存
type loginPidUtil struct {
	uid uint64
}

func LoginPidUtil(uid uint64) *loginPidUtil {
	sessUtil := &loginPidUtil{}
	sessUtil.uid = uid
	return sessUtil
}

// 字段表
type LoginpidInfo struct {
	Pid uint64 `redis:"Pid"` //同一个uid下 已经登录的 玩家角色id
}

const (
	loginpidPrefix  = "loginpid"
	deviceKeyPrefix = "LoginDevice:"
	RedisPid        = "Pid"
)

// 获取loginpid表的Key
func (util *loginPidUtil) Key() string {
	return fmt.Sprintf("%s:%d", loginpidPrefix, util.uid)
}

// 获取session表的key
func (util *loginPidUtil) SessionKey(pid uint64) string {
	return fmt.Sprintf("%s:%d", sessionPrefix, pid)
}

// // 检查表是否存在
// func (util *loginPidUtil) IsExisted(c *redislib.RedisHandleModel) (bool, error) {
// 	if c == nil {
// 		c = GetSessionRedis()
// 		defer c.Dispose()
// 	}

// 	reply, err := c.Do("EXISTS", util.Key())
// 	if err != nil {
// 		return false, err
// 	}
// 	return redis.Bool(reply, nil)
// }

// 延长保留时间
func (util *loginPidUtil) Expire() {
	c := GetSessionRedis()
	defer c.Close()
	c.Expire(c.Ctx, util.Key(), Expire_Time)
}

// 设置新的PID进去，获取原来的PID
func (util *loginPidUtil) GetSetPID(pid uint64) (uint64, error) {
	c := GetSessionRedis()
	defer c.Close()
	return c.GetSet(c.Ctx, util.Key(), pid).Uint64()
}

// 请看  LoginpidInfo 的调用,写入是在 CheckKick 函数中,通过HMSet 写入的Hash结构,非这里的 string 结构
//func (util *loginPidUtil) SaveLoginPidInfo(info *LoginpidInfo, c *redislib.RedisHandleModel) bool {
//	if c == nil {
//		c = GetSessionRedis()
//		defer c.Dispose()
//	}
//
//	// result = 0 写入失败
//	if result, err := common.NewString(c.Set(util.Key(), common.NewStringAny(info.Pid).String(), -1, redislib.Set_NX)); err == nil {
//		return result == 1
//	}
//	return false
//}

// func (util *loginPidUtil) GetPid(tx *redis.Tx) (uint64, error) {
// 	// 拿到loginpid的 玩家上次登录pid
// 	repid, err := tx.Do("HGET", util.Key(), RedisPid)

// 	if err != nil {
// 		return 0, err
// 	}
// 	return redis.Uint64(repid, err)
// }

// //////////////////////////////////////////////////////////

func (utilmd *loginPidUtil) KeyDevice() string {
	return fmt.Sprint(deviceKeyPrefix, utilmd.uid)
}

// 写入数据
func (utilmd *loginPidUtil) SetDeviceInfo(data *DeviceInfo) {
	rd := GetLoginRedis()
	defer rd.Dispose()
	datas, _ := data.Marshal()
	if err := rd.SetNX(rd.Ctx, utilmd.KeyDevice(), datas, Expire_Time).Err(); err != nil {
		logger.Errorf("loginPidUtil.SetDeviceInfo:%s", err)
	}
	// if _, err := rd.SetBytes(utilmd.KeyDevice(), datas, utilmd.GetTTLSecond(), redislib.Set_No_NX_XX); err != nil {
	// 	logger.Error("loginPidUtil.SetDeviceInfo:", err)
	// }
}

// 刷新时间
func (utilmd *loginPidUtil) TTLDeviceInfo() {
	rd := GetLoginRedis()
	defer rd.Dispose()
	if err := rd.Expire(rd.Ctx, utilmd.KeyDevice(), Expire_Time).Err(); err != nil {
		logger.Error("loginPidUtil.ReDeviceInfoEx:", err)
		return
	}
}

// 获取数据
func (utilmd *loginPidUtil) GetDeviceInfo() (result *DeviceInfo) {
	rd := GetLoginRedis()
	defer rd.Dispose()
	if datas, err := rd.Get(rd.Ctx, utilmd.KeyDevice()).Result(); err != nil {
		logger.Error("loginPidUtil.GetDeviceInfo:", err)
		return &DeviceInfo{
			Values: url.Values{},
		}
	} else {
		result = new(DeviceInfo)
		result.Unmarshal([]byte(datas))
		return result
	}
	// if result, err := rd.GetBytes(utilmd.KeyDevice()); err != nil {
	// 	logger.Error("loginPidUtil.GetDeviceInfo:", err)
	// 	return &DeviceInfo{
	// 		Values: url.Values{},
	// 	}
	// } else {
	// 	var deviceInfo = &DeviceInfo{
	// 		Values: url.Values{},
	// 	}
	// 	_ = deviceInfo.Unmarshal(result)
	// 	return deviceInfo
	// }
}

// DeviceInfo NOTE: 以下是数据埋点  需要的 客户端透传字段：该部分参数由GSSDK透传
//
//	https://hara1d9t8lv.feishu.cn/wiki/HBitwldtzi9yiZkWKI3cHnzFnJc
//
// one_id	          string	√	设备标识
// device_id	        string	√	设备ID
// app_package_name	string		APP包体名称
// device_model	    string	√	设备型号
// os_version	      string		操作系统版本
// cpsid	            string	√	渠道分包ID
// language	        string	√	语言
// channel	          string	√	用户渠道
// os_type	          string	√	操作系统
// app_version	      string		APP版本（与客户端一致）
// app_version_code	string		APP版本CODE（细分版本）
// user_id	          string	√	GSSDK账号ID
// yoka_id	          string	√	渠道侧用户ID
// user_type	        string	√	账号类型\注册方式等(微信注册、手机注册、游客登录等)
// 其他参数 参考: https://docs.dobest.cn/docs/sdk-service-docs/sdk-ip-address-query-1f99gr6f7vkm07
type DeviceInfo struct {
	//PlatformID string
	//ClientVer  string
	//OS         string
	//DeviceID   string
	//DeviceName string
	//ChannelID string
	url.Values
}

func (deviceInfo *DeviceInfo) GetDeviceId() string {
	return deviceInfo.Values.Get("device_id")
}
func (deviceInfo *DeviceInfo) SetDeviceId(val string) {
	deviceInfo.Values.Set("device_id", val)
}
func (deviceInfo *DeviceInfo) GetDeviceName() string {
	return deviceInfo.Values.Get("device_model")
}
func (deviceInfo *DeviceInfo) SetDeviceName(val string) {
	deviceInfo.Values.Set("device_model", val)
}
func (deviceInfo *DeviceInfo) GetChannelID() string {
	return deviceInfo.Values.Get("channel")
}
func (deviceInfo *DeviceInfo) SetChannelID(val string) {
	deviceInfo.Values.Set("channel", val)
}
func (deviceInfo *DeviceInfo) GetAppVer() string {
	return deviceInfo.Values.Get("app_version")
}
func (deviceInfo *DeviceInfo) SetAppVer(val string) {
	deviceInfo.Values.Set("app_version", val)
}
func (deviceInfo *DeviceInfo) GetPlatformID() string {
	return deviceInfo.Values.Get("PlatformID")
}
func (deviceInfo *DeviceInfo) SetPlatformID(val string) {
	deviceInfo.Values.Set("PlatformID", val)
}
func (deviceInfo *DeviceInfo) GetOS() string {
	return deviceInfo.Values.Get("os_type")
}
func (deviceInfo *DeviceInfo) SetOS(val string) {
	deviceInfo.Values.Set("os_type", val)
}

// var _ proto.Unmarshaler = (*DeviceInfo)(nil)
func (deviceInfo *DeviceInfo) Unmarshal(bytes []byte) error {
	vals, err := url.ParseQuery(string(bytes))
	deviceInfo.UnmarshalFromUrlValues(vals)
	return err
}

// var _ proto.Marshaler = (*DeviceInfo)(nil)
func (deviceInfo *DeviceInfo) Marshal() ([]byte, error) {
	vals := deviceInfo.MarshalToUrlValues()
	return []byte(vals.Encode()), nil
}

// DeviceInfo 按照urlValues 进行序列化
func (deviceInfo *DeviceInfo) MarshalToUrlValues() url.Values {
	return deviceInfo.Values
}

// DeviceInfo 按照urlValues 进行反序列化
func (deviceInfo *DeviceInfo) UnmarshalFromUrlValues(values url.Values) *DeviceInfo {
	//deviceInfo = &DeviceInfo{}
	deviceInfo.Values = values
	return deviceInfo
}
